#include "cmdfifo.h"
#include "option.h"
#include "smset.h"
#define    DIM(x)  (sizeof(x)/sizeof(x[0])) 

static int sm_cb_parse_line(int total , int num, char *msg, int len);
static int sm_string_split_parse(char *msg , int len, char separator, 
        int (*callback)(int total, int num, char *msg, int len));
#define SM_ERROR_UNIT_INCONSISTENT    1
#define SM_ERROR_TIME_FORMAT          2
#define SM_ERROR_DP_INFO              3
#define SM_ERROR_DP_NO                4
#define SM_ERROR_DATA_FORMAT          5
#define SM_ERROR_CMD_INVALID          6
#define SM_ERROR_TEL_NO               7
#define SM_ERROR_SYNTAX               8
#define SM_OK_SETUP                   9
#define SM_ERROR_TEL_OVERFLOW         10
#define SM_ERROR_TEL_EXIST            11

//存储短信中获取的设置信息
typedef struct sm_set_dp
{
    int dp_no;
    char oper; //操作  1 --参数设置
    option_dp_t dp_info;
}sm_set_dp_t;

//错误信息对应处理句柄
typedef struct sm_error_handle
{
    char type;
    char *info;
}sm_error_handle_t;

/*cmd_fifo_cmd_handle_t l_inner_cmd_handle[]=*/
/*{*/
    /*[>{1,sm_inner_cmd_handle_view_dp}, //查询大棚温湿度<]*/
    /*[>{2,sm_inner_cmd_handle_list_tel},//查询手机号<]*/
    /*[>{3,sm_inner_cmd_handle_resp_stat},//命令执行状态<]*/
    /*[>{4,sm_inner_cmd_handle_balance},//处理余额<]*/
    /*[>{5,sm_inner_cmd_handle_query},//发送短信查询余额<]*/
/*};*/

const sm_error_handle_t l_sm_error_handle[]={
    {SM_ERROR_UNIT_INCONSISTENT ,  "数据单位不统一错误！\n"},
    {SM_ERROR_TIME_FORMAT       ,  "时间数据格式错误！\n"  },
    {SM_ERROR_DP_INFO           ,  "大棚信息输入有误！\n"},
    {SM_ERROR_DP_NO             ,  "大棚号输入有误！\n"},
    {SM_ERROR_DATA_FORMAT       ,  "数据格式错误！\n"},
    {SM_ERROR_CMD_INVALID       ,  "非法指令！\n"},
    {SM_ERROR_TEL_NO            ,  "电话号输入错误！\n"},
    {SM_ERROR_SYNTAX            ,  "语法错误！\n"},
    {SM_OK_SETUP                ,  "操作成功！\n"},
    {SM_ERROR_TEL_OVERFLOW      ,  "电话号已满！\n"},
    {SM_ERROR_TEL_EXIST         ,  "电话号码已存在！\n"},
};

/*存储从短信读取的配置信息*/
static sm_set_dp_t oset_dp;
static sm_set_dp_t *l_set_dp = &oset_dp;
static option_t *l_option;

/*******************************************************************************
 * Function:      sm_data_parse()
 * Description:   分析短信数据
 * Calls:         text_conv_pdu2asc()
 *                sm_text_split2line_proc() 
 * Called By:      
 * Input:         msg  --信息正文数据(ASCII)格式
 * Return:        void
 * Others:        msg 必须为可回写存储区,转换后字符串会回填到原位置
 ******************************************************************************/
void pdu_sms_parse(option_t *option, char *msg)
{
    int ret = -1;
    int msglen;
    int i;
    int a = 0; //记录当期位置

    msglen = strlen(msg);
    if (option != NULL)
    {
        l_option = option;
        /*text_conv_pdu2asc(data, data, strlen(data)); //转换编码*/

        for (i = 0; i <= msglen; i ++)
        {
            if (msg[i] == '\n' || msg[i] == '\r'|| i == msglen - 1)
            {
                msg[i] = '\0';
                if (strlen (&msg[a]) == 0) continue ; //如果是空行，不处理
                ret = _sms_line_proc (&msg[a], strlen (&msg[a]));
                a = i + 1;
            }
        }
        /*ret = sm_text_split2line_proc(data, ); //转换编码后的字符串按行进行处理*/
    }
}

static void _sms_output_res(char type);

//按行处理短信正文
int _sms_line_proc(char *msg, int len)
{
    int i;
    int ret = SM_ERROR_SYNTAX;
    ret = sm_string_split_parse (msg, len, '#', sm_cb_parse_line);
    /*ret = sm_string_split_parse (msg, len, '#', sm_cb_demo);*/
    //保存设置参数
    if (ret == SM_OK_SETUP && l_set_dp->oper == 1)
    {
        l_option->dp[l_set_dp->dp_no] = l_set_dp->dp_info;

        if((!l_option->dp[l_set_dp->dp_no].temperature_low)&&(!l_option->dp[l_set_dp->dp_no].temperature_high))
        {
            l_option->dp[l_set_dp->dp_no].temperature_switch = 0;
        }
        else
        {
            l_option->dp[l_set_dp->dp_no].temperature_switch = 1;
        }
        if((!l_option->dp[l_set_dp->dp_no].humidity_low)&&(!l_option->dp[l_set_dp->dp_no].humidity_high))
        {
            l_option->dp[l_set_dp->dp_no].humidity_switch = 0;
        }
        else
        {
            l_option->dp[l_set_dp->dp_no].humidity_switch = 1;
        }
        if(!l_set_dp->dp_no)
        {
            for(i = 0; i < 21; i++)
            {
                l_option->dp[i].temperature_switch = l_option->dp[l_set_dp->dp_no].temperature_switch; 
                l_option->dp[i].humidity_switch = l_option->dp[l_set_dp->dp_no].humidity_switch;			  
            }
        }

        option_set (l_option);
        /*printf ("[OPTION]参数设置成功\n");*/
    }
    _sms_output_res(ret);
    /*sm_inner_cmd_loop ();*/
    return ret;
}

/*回复信息处理*/
static void _sms_output_res(char type)
{
    sm_inner_cmd_push_fifo (3, type);
}


/*第三层解析，解析时间参数*/
int sm_cb_parse_time(int total , int num, char *msg, int len)
{
    static int flag = 0;  //区分时间  0 起始、1 终止时间
    static unsigned char time[2] = {0};
    /*验证数据是否正确*/
    if (total != 2) //是否分成了两个字段
    {
        return SM_ERROR_TIME_FORMAT;      //  "时间数据格式错误！\n"
    }
    else //分成两两个字段
    {
        if (sm_string_is_num(msg, len) == 0)
        {
            time[num - 1] = atoi (msg);
            if (time[0] >= 24 || time[1] >= 60 )
            {
                time[0]=0;
                time[1]=0;
                return SM_ERROR_TIME_FORMAT;      //  "时间数据格式错误！\n"
            }

            if (flag == 0) //起始时间
            {
                if (num == total)
                {
                    /*printf ("起始时间 %02d:%02d\n",time[0], time[1]);*/
                    l_set_dp->dp_info.time_start = (uint16_t)(time[0] << 8 | time[1]);
                    fflush(stdout);
                    flag = 1;
                }
            }
            else if (flag == 1) //终止时间
            {
                time[num - 1] = atoi (msg);
                if (num == total)
                {
                    /*printf ("终止时间 %02d:%02d\n",time[0], time[1]);*/
                    l_set_dp->dp_info.time_stop = (uint16_t)(time[0] << 8 | time[1]);
                    fflush(stdout);
                    flag = 0;
                }
            }
        }
        else
        {
            return SM_ERROR_TIME_FORMAT;      //  "时间数据格式错误！\n"
        }
    }

    return SM_OK_SETUP;
}

/*第二层解析,解析参数*/
int sm_cb_parse_field(int total , int num, char *msg, int len)
{
    static int flag = 0; //本次处理数据类型（'C'-温度 'T'-湿度）*/
    static char temperature[2]={0};
    static char hum[2]={0};

    /*验证数据是否正确*/
    if (total != 2 || len == 0) //是否分成了两个字段,且长度不为0
    {
        return SM_ERROR_DATA_FORMAT; //      ,  "数据格式错误！\n",
    }
    else //分成两两个字段
    {
        if (sm_string_is_num (msg, len-1) == 0 && 
                *(msg+len-1) == 'C'
           )
        {
            if (num == 1) flag = 'C';
            if (*(msg+len-1) != flag)
            {
                return SM_ERROR_UNIT_INCONSISTENT; //  "数据单位不统一错误！\n"
            }
            temperature[num-1] = atoi (msg);
            if (num == total)
            {
                /*printf ("温度上限值: %d\n",max(temperature[0], temperature[1]));*/
                /*printf ("温度下限值: %d\n",min(temperature[0], temperature[1]));*/
                l_set_dp->dp_info.temperature_high = (_max(temperature[0], temperature[1]))*10;
                l_set_dp->dp_info.temperature_low  = (_min(temperature[0], temperature[1]))*10;
            }
        }
        else if (sm_string_is_num (msg, len-1) == 0 && 
                *(msg+len-1) == '%'
                )
        {
            if (num == 1) flag = '%';
            if (*(msg+len-1) != flag)
            {
                return SM_ERROR_UNIT_INCONSISTENT; //  "数据单位不统一！\n"
            }
            hum[num-1] = atoi (msg);
            if (num == total)
            {
                /*printf ("湿度上限值: %d\n",max(hum[0], hum[1]));*/
                /*printf ("湿度下限值: %d\n",min(hum[0], hum[1]));*/
                l_set_dp->dp_info.humidity_high = (_max(hum[0], hum[1]))*10;
                l_set_dp->dp_info.humidity_low  = (_min(hum[0], hum[1]))*10;
            }
        }
        else
        {
            if (num == 1) flag = ':';
            if (strstr(msg,":") == NULL || flag != ':')
            {
                return SM_ERROR_UNIT_INCONSISTENT; //  "数据单位不统一错误！\n"
            }
            if (sm_string_split_parse (msg, len, ':', sm_cb_parse_time) != SM_OK_SETUP)
            {
                return SM_ERROR_TIME_FORMAT;      //  "时间数据格式错误！\n"
            }
        }
    }

    if (num == total)
    {
        flag = 0;
    }

    /*printf ("[buffer] %s\n", msg);*/
    /*printf ("[a] %d\t[FT] %d\t[FC] %d\t[buffer] %s\n", a, total, num,  msg);*/
    return SM_OK_SETUP;
}


int sm_cb_demo(int total , int num, char *msg, int len)
{
    int dp_num = 0; //大棚序号
    int ret = 0;

    /*printf ("[%d/%d] %s\t[len]%d\n", total, num, msg, len);*/
    if (sm_string_is_num (msg, len) == -1)
    {
        return SM_ERROR_DP_NO;
    }
    else
    {
        dp_num = atoi(msg);
        ret = 0;
        sm_inner_cmd_push_fifo (1, dp_num); //查询大棚
        /*ret = sm_option_view_dp_info(dp_num);*/
    }

    return ret;
}

/*******************************************************************************
 * Function:      sm_option_set_tel()
 * Description:   
 * Calls:         
 * Called By:      
 * Input:         msg   --字符串
 *                len   --字符串长度
 * Return:        int
 * Others:        None
 ******************************************************************************/
int sm_option_set_tel(char *msg, int len)
{
    int ret = SM_ERROR_CMD_INVALID;
    if (len < 4) return SM_ERROR_SYNTAX;
    if (msg[0] == 'T' && //与电话设置有关
            msg[1] == 'E' &&
            msg[2] == 'L'
       )
    {
        //增加手机号
        if (msg[3] == '+')
        {
            ret = sm_option_tel_add(&msg[4], len - 4);
        }
        //删除手机号
        else if (msg[3] == '-')
        {
            if (sm_telnum_verify(&msg[4], len - 4) == 0)
            { //正常处理
                sm_option_tel_del(msg);
                sm_inner_cmd_push_fifo(3, SM_OK_SETUP);
                return 0;
            }
            else
            {
                ret = SM_ERROR_TEL_NO;
            }
        }
        //查询手机号
        else if (msg[3] == '?')
        {
            /*printf ("查询手机号\n");*/
            sm_inner_cmd_push_fifo(2, SM_OK_SETUP);//查询手机号
            return 0;
        }
        //按索引处理手机号
        else
        {
            if (strstr(&msg[3], "-"))
            {
                /*ret = sm_string_split_parse (&msg[3], strlen(&msg[3]), '-', sm_option_tel_del_by_index);*/
            }
            else if (strstr(&msg[3], "+"))
            {
                /*ret = sm_string_split_parse (&msg[3], strlen(&msg[3]), '+', sm_option_tel_add_by_index);*/
            }
            else
            {
                ret = SM_ERROR_SYNTAX;
            }
        }
    }
    return ret;
}

 /*******************************************************************************
 * Function:      sm_string_split_parse()
 * Description:   分段处理字符串,用分隔符将行分成N段,并对每段进行处理
 * Calls:         calloc
 * 
 * Called By:     sm_line_proc()
 * Input:         msg  --字符串
 * 
 * Return:        0  --执行成功
 *                -1 --执行失败
 *                -2 --内存分配错误
 * Others:        None
 ******************************************************************************/
static int sm_string_split_parse(char *msg , int len, char separator, 
        int (*callback)(int total, int num, char *msg, int len))
{
    int i;
    int count = 0; //记录当前字段的字符数
    int current_field_NO = 0; //当前字段序号
    int field_total = 1;
    char *buffer = NULL;
    int ret = -1;
    char *last_addr = msg; //记录上个字段结束的地址,下一字段的起始地址
    for (i = 0; i < len ; i ++) //计算字段总数
    {
        if (msg[i] == separator)
        {
            field_total ++ ;
        }
    }

    /* 12#13#1 */
    for (i = 0; i <= len ; i ++)
    {
        if (msg[i] == separator || i == len)
        {
            current_field_NO ++ ;
            buffer = (char *)calloc(1,count+1);
            if (buffer == NULL)
            {
                return -1;
            }
            /*if (i == len - 1 && msg[i] != separator)*/
            if (i == len)
            {
                count ++;
            }
            memcpy (buffer, last_addr, count);
            last_addr = &msg[i+1];
            if (callback == NULL)
            {
                free (buffer);
                return -2;
            }
            ret = callback (field_total, current_field_NO, buffer, strlen (buffer));
            free (buffer);
            buffer = NULL;
            count = 0;
            /*if (ret != 0 || ret != SM_OK_SETUP)*/
            if (ret == SM_OK_SETUP || ret == 0)
                continue;

            return ret;
            /*i++;*/
        }
        count ++;
    }
    return ret;
}

/*第一层解析*/
static int sm_cb_parse_line(int total , int num, char *msg, int len)
{
    int ret = 0;

    sm_string_to_upper (msg, len); //转换成大写

    /*printf ("%s\n", msg);*/
    if (total == 1)//只有一个字段
    {

        if (msg[0] >= '0' && msg[0] <= '9')
        {//++表明内容是纯数字的短信
            ret = sm_string_split_parse (msg, len, ' ', sm_cb_demo);
            /*dp_num = atoi(msg);*/
            /*printf ("[ALL]%s\n", msg);*/
            /*ret = sm_option_view_dp_info(dp_num);*/
        }//--表明内容是纯数字的短信
        else
        {
            ret = sm_option_set_tel(msg, len); //设置、显示电话号码
        }
        return ret;
    }
    else
    {
        /*printf ("[FT] %d\t[FC] %d\t[buffer] %s\n", total, num,  msg);*/
        if (len == 0)
        {
            return SM_ERROR_DP_INFO;       //  "大棚信息输入有误\n"
        }
        if (num == 1)//第一个字段是大棚序号
        {
            if (sm_string_is_num (msg, len) == 0)
            {
                /*printf("设置%02d号大棚\n", atoi (msg));*/
                if (l_set_dp == NULL) //空指针
                {
                    return -1;
                }
                l_set_dp->oper = 1; //设置参数，并需要保存
                l_set_dp->dp_no = atoi (msg);
                l_set_dp->dp_info = l_option->dp[(int)l_set_dp->dp_no]; //获取对应大棚的数据
                ret = 0;
            }
            else 
            {
                ret = SM_ERROR_DP_NO;  //      "设置大棚，大棚号输入有误\n"
            }
        }
        else
        {
            ret = sm_string_split_parse (msg, len, '-', sm_cb_parse_field);
            return ret;
        }
    }
    return SM_OK_SETUP;
}



//回复命令执行数据
static int sm_inner_cmd_handle_resp_stat(char cmd, char param)
{
    int i;
    for (i = 0; i < DIM(l_sm_error_handle); i ++)
    {
        if (param == l_sm_error_handle[i].type)
        {
            SMS_printf ("[命令]");
            SMS_printf (l_sm_error_handle[i].info);
        }
    }
    return 0;
}

//查询手机号
static int sm_inner_cmd_handle_list_tel(char cmd, char param)
{
    int i, j;
    SMS_printf("所有手机号码：\n");
    for (i = 0; i < 4; i ++)
    {
        if (l_option->telephone[i].number[0] == 1)
        {
            for (j = 0; j < 11; j ++)
            {
                SMS_printf ("%d", l_option->telephone[i].number[j]);
            }
            SMS_printf ("\n");
        }
    }
    SMS_flush();
    return 0;
}
